package org.mozhu.mboot.backend.security;

import com.google.common.base.Joiner;
import io.jsonwebtoken.Claims;
import io.jsonwebtoken.JwtBuilder;
import io.jsonwebtoken.Jwts;
import io.jsonwebtoken.SignatureAlgorithm;
import org.joda.time.LocalDateTime;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.security.core.Authentication;
import org.springframework.security.core.GrantedAuthority;
import org.springframework.stereotype.Service;

import javax.crypto.spec.SecretKeySpec;
import javax.xml.bind.DatatypeConverter;
import java.security.Key;
import java.util.ArrayList;
import java.util.Collection;
import java.util.Date;
import java.util.List;

@Service
public class JWTService {

    private String secret;

    private Integer expiration;


    public String generateToken(Authentication auth) {
        Collection<? extends GrantedAuthority> authorities = auth.getAuthorities();
        List roleList = new ArrayList<>();
        for (GrantedAuthority grantedAuthority : authorities) {
            roleList.add(grantedAuthority.getAuthority());
        }

        SignatureAlgorithm signatureAlgorithm = SignatureAlgorithm.HS256;
        //生成签名密钥
        byte[] apiKeySecretBytes = DatatypeConverter.parseBase64Binary(getSecret());
        Key signingKey = new SecretKeySpec(apiKeySecretBytes, signatureAlgorithm.getJcaName());

        //添加构成JWT的参数
        JwtBuilder builder = Jwts.builder()
                .setSubject(auth.getName())
                .setAudience(Joiner.on(",").join(roleList))
                .signWith(signatureAlgorithm, signingKey)
                .setExpiration(new LocalDateTime().plusMinutes(getExpiration()).toDate())
                .setNotBefore(new Date(System.currentTimeMillis()));
        return builder.compact();

    }

    public Claims parseToken(String token) {
        // Use JWT parser to check if the signature is valid with the Key "secretkey"
        return Jwts.parser().setSigningKey(getSecret()).parseClaimsJws(token).getBody();
    }

    public String getSecret() {
        return secret;
    }

    @Value("${jwt.secret}")
    public void setSecret(String secret) {
        this.secret = secret;
    }


    public Integer getExpiration() {
        return expiration;
    }

    @Value("${jwt.expiration}")
    public void setExpiration(Integer expiration) {
        this.expiration = expiration;
    }
}
